package com.honey.solr;
import java.util.List;

import com.movie.manager.model.Condition;
import com.movie.manager.model.GeneratedCriteria;
import com.movie.manager.model.OrderModel;
import com.movie.manager.model.GeneratedCriteria.Criterion;



public class test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Condition<OrderModel> c = new Condition<OrderModel>( new OrderModel()) ;
		c.or().andEqualTo(OrderModel.OrderTableField.ID,123);
		c.or().andEqualTo(OrderModel.OrderTableField.ID,12).andBetween(OrderModel.OrderTableField.ID,1,4);
		test t = new test();
		String s = t.conditionAdapter(c) ;
		System.out.println(s);
	}

	@SuppressWarnings("unchecked")
	private  String conditionAdapter(Condition condition){
		StringBuilder query = new StringBuilder();
		List<GeneratedCriteria> list = condition.getOredCriteria() ;
		boolean or =false ;
		LuceneQueryAdapter adapter = new LuceneQueryAdapter();
		for(GeneratedCriteria gc : list  ){
			boolean and =false ;
			if( or ) query.append(" OR ");else or =true;
			query.append('(');
			List<Criterion> l =  gc.getCriteria();
			for(Criterion criterion : l){
				if( and ) query.append(" AND ");else and =true ;
				switch ( criterion.getTerm() ){
					case IS_NULL:
						break;
					case IS_NOT_NULL:
						break;
						
					case GREATER_THAN:
					case GREATER_THAN_OR_EQUAL_TO:
						query.append( adapter.greater(criterion));
						break;
					
					case LESS_THAN:
					case LESS_THAN_OR_EQUAL_TO:
						query.append( adapter.less(criterion));
						break;
					case IN:
						query.append( adapter.in(criterion));
						break;	
					case NOT_IN:
						query.append( adapter.notIn(criterion));
						break;
					case BETWEEN:
						query.append( adapter.between(criterion));
						break;		
						
					case NOT_BETWEEN:
						query.append( adapter.notBetween(criterion));
						break;
						
					case EQUAL_TO:
					case LIKE:
						query.append( adapter.like(criterion));
						break;
						
					case NOT_EQUAL_TO:
					case NOT_LIKE:
						query.append( adapter.notLike(criterion));
						break;		
				}
			}

			query.append(')');
		}
		return query.toString();
	}
	
	/**
	 * 转换成Lucene能够识别的查询语句
	 * @author Administrator
	 *
	 */
	@SuppressWarnings("unchecked")
	class LuceneQueryAdapter{
		
		public StringBuilder greater(Criterion criterion ){
			Object value = criterion.getValue();
			return between(criterion.getName(),value ==null ?null:value.toString() , null);
		}
		
		public StringBuilder less(Criterion criterion ){
			Object value = criterion.getValue();
			return between(criterion.getName(), null , value ==null ?null:value.toString());
		}
		
		public StringBuilder between(Criterion criterion ){
			Object value1 = criterion.getValue();
			Object value2 = criterion.getSecondValue();
			return between(criterion.getName(), value1 ==null?null:value1.toString() , value2 ==null?null:value2.toString());
		}
		public StringBuilder notBetween(Criterion criterion ){
			return not(between(criterion));
		}
		
		public StringBuilder like(Criterion criterion ){
			Object value = criterion.getValue();
			return like(criterion.getName(), value ==null?null:value.toString());
		}
		
		public StringBuilder notLike(Criterion criterion ){
			return not(like(criterion));
		}
		public StringBuilder in(Criterion criterion ){
			return in(criterion.getName(), (List<?>)criterion.getValue(), false);
		}
		public StringBuilder notIn(Criterion criterion ){
			return in(criterion.getName(), (List<?>)criterion.getValue(), true);
		}
		
		/**
		 * Lucene不支持in查询,使用使用equal查询模拟in查询.
		 * @param name
		 * @param list
		 * @param isNot
		 * @return
		 */
		private StringBuilder in(Enum<?> name,List<?> list,boolean isNot){
			StringBuilder answer = new StringBuilder('(');
			boolean and =false ;
			for(Object obj : list  ){
				if(obj != null){
					if( and ) answer.append(" AND ");else and = true ;
					StringBuilder tmp = like( name, obj.toString());
					if( isNot ){
						 not(tmp) ;
					}
					answer.append(tmp);
				}
			}
			return answer.append(')');
		}
		
		/**
		 * Lucene查询. 在查询条件之前加入"-".
		 * @param sb
		 * @return
		 */
		private StringBuilder not(StringBuilder sb){
			return sb.insert(0, '-'); 
		}
		
		/**
		 * Lucene的模糊查询格式是 field:value
		 * @param name
		 * @param value
		 * @return
		 */
		private StringBuilder like (Enum<?> name,String value){
			StringBuilder answer = new StringBuilder();
			answer.append(name).append(':').append(value);
			return answer ;
		}
		
		/**
		 * 等于区间查询. Lucene的区间查询格式是: field:[ value1 TO value2 ], 意义如下:
		 * 	<ul>
		 * 		<li>value1和value2同时不为null, 意义是: field>=value1 and field<=value2 </li>
		 *  	<li>value1为null value2不为null, 意义是: field>=value1</li>
		 *  	<li>value1不为null value2为null, 意义是: field<=value2</li>
		 *  </ul>
		 * @param name
		 * @param value1
		 * @param value2
		 * @return
		 */
		private StringBuilder between(Enum<?> name,String value1,String value2 ){
			StringBuilder answer = new StringBuilder();
			if( value1 == null || value1.length()==0){
				value1 ="*";
			}
			if( value2 == null || value2.length()==0){
				value2 ="*";
			}
			answer.append(name).append(new char[]{':','['})
			.append(value1).append(new char[]{' ','T','O',' '}).append(value2)
			.append(']');
			return answer ;
		}
	}
}
